#include "wayland-glib.h"
#include <stdio.h>
#include <stdlib.h>
#include <wayland-server.h>
#include <wayland-client.h>
#include <glib.h>
#include <unistd.h>

// Wayland GSource structure
typedef struct {
    GSource source;
    GPollFD pfd;
    struct wl_display *display;
} WaylandSource;

// Prepare callback for the GSource
static gboolean wayland_prepare(GSource *source, gint *timeout) {
    *timeout = -1;
    return FALSE;
}

// Check callback for the GSource
static gboolean wayland_check(GSource *source) {
    WaylandSource *wayland_source = (WaylandSource *)source;
    return wayland_source->pfd.revents & G_IO_IN;
}

// Dispatch callback for the GSource
static gboolean wayland_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
    WaylandSource *wayland_source = (WaylandSource *)source;
    struct wl_event_loop *event_loop = wl_display_get_event_loop(wayland_source->display);
    if (wayland_source->pfd.revents & G_IO_IN) {
        wl_display_flush_clients(wayland_source->display);
        if (wl_event_loop_dispatch(event_loop, 0) < 0) {
            fprintf(stderr, "Failed to dispatch Wayland events\n");
            return G_SOURCE_REMOVE;
        }
    }
    return G_SOURCE_CONTINUE;
}

// GSourceFuncs for Wayland
static GSourceFuncs wayland_source_funcs = {
    .prepare = wayland_prepare,
    .check = wayland_check,
    .dispatch = wayland_dispatch,
    .finalize = NULL,
};

// Function to create the Wayland GSource
GSource *wl_glib_source_new(struct wl_display *display) {
    GSource *source;
    WaylandSource *wayland_source;

    source = g_source_new(&wayland_source_funcs, sizeof(WaylandSource));
    wayland_source = (WaylandSource *)source;

    struct wl_event_loop *event_loop = wl_display_get_event_loop(display);

    wayland_source->display = display;
    wayland_source->pfd.fd = wl_event_loop_get_fd(event_loop);
    wayland_source->pfd.events = G_IO_IN | G_IO_ERR | G_IO_HUP;
    g_source_add_poll(source, &wayland_source->pfd);

    return source;
}
